/**
 *
 */
package com.siteseat.common.misc;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;

import com.siteseat.common.exception.InternalException;

/**
 *
 */
public class FileHelper {

  public static File getFileFromURL( URL url ) throws IOException {
    try {
      return new File( URLDecoder.decode( url.getFile(), "utf-8" ) );
    } catch( UnsupportedEncodingException e ) {
      throw new IOException( e );
    }
  }

  /**
   * @param f
   * @throws InternalException
   */
  public static File validateFolder( String f ) throws IOException {
    File r = new File(f);
    validateFolder( r );
    return r;
  }

  /**
   * @param f
   * @throws InternalException
   */
  public static void validateFolder( File f ) throws IOException {
    if( f.exists() == false ) {
      throw new IOException( "<" + f.getAbsolutePath() + "> doesn't exist" );
    }
    if( f.isDirectory() == false ) {
      throw new IOException( "<" + f.getAbsolutePath() + "> is not a folder" );
    }
  }

  /**
   * @param f
   * @throws InternalException
   */
  public static File validateFile( String f ) throws IOException {
    File r = new File(f);
    validateFile( r );
    return r;
  }

  /**
   * @param f
   * @throws InternalException
   */
  public static void validateFile( File f ) throws IOException {
    if( f.exists() == false ) {
      throw new IOException( "<" + f.getAbsolutePath() + "> doesn't exist" );
    }
    if( f.isFile() == false ) {
      throw new IOException( "<" + f.getAbsolutePath() + "> is not a file" );
    }
  }

  /**
   * @param folder
   * @return true if created, false if already exists
   * @throws InternalException
   */
  public static boolean createFileIfNotExists( File f ) throws IOException {
    createFolderIfNotExists( f.getParentFile() );

    if( f.exists() == false ) {
      if( f.createNewFile() == false ) {
        throw new IOException( "Failed to create file <" + f.getAbsolutePath() + ">" );
      }
      return true;
    } 
    
    if( f.isFile() == false ) {
      throw new IOException( "<" + f.getAbsolutePath() + "> is not a file" );
    }
    
    return false;
  }

  /**
   * @param folder
   * @throws InternalException
   */
  public static void createFolderIfNotExists( File f ) throws IOException {
    if( f.exists() == false ) {
      if( f.mkdirs() == false ) {
        throw new IOException( "Failed to create file <" + f.getAbsolutePath() + ">" );
      }
    } else if( f.isDirectory() == false ) {
      throw new IOException( "<" + f.getAbsolutePath() + "> is not a folder" );
    }
  }

  /**
   * @param folder
   * @throws InternalException
   */
  public static void ensureEmptyFolder( File f, boolean createFolderIfNotExists ) throws IOException {
    if( createFolderIfNotExists ) {
      createFolderIfNotExists( f );
    } else {
      FileHelper.validateFolder( f );
    }

    if( ArrayUtils.isEmpty( f.list() ) == false ) {
      throw new IOException( "<" + f.getAbsolutePath() + "> is not empty" );
    }
  }

  /**
   * @param f
   * @return
   * @throws IOException
   */
  public static byte[] readIntoBytes( File f ) throws IOException {
    InputStream ins = null;
    try {
      ins = new FileInputStream( f );
      return IOUtils.toByteArray( ins );
    } finally {
      IOUtils.closeQuietly( ins );
    }
  }

  /**
   * @param fileName
   * @return
   */
  public static String extractFileTitle( String fileName ) {
    int dot = fileName.lastIndexOf( '.' );
    if( dot >= 0 ) {
      return fileName.substring( 0, dot );
    }
    return fileName;
  }

  /**
   * @param f
   * @return
   * @throws IOException
   */
  public static long checkedFileLength( File f, long maximalSize, int minimalSize ) throws IOException {
    long lLen = f.length();
    if( lLen > maximalSize ) {
      throw new IOException( "Too large file <" + f.getAbsolutePath() + ">" );
    }
    if( lLen < minimalSize ) {
      throw new IOException( "Too small file <" + f.getAbsolutePath() + ">" );
    }

    return lLen;
  }

  /**
   * @param ins
   * @return
   * @throws IOException
   */
  /*
  public static byte[] readIntoMemory( Rater rater, String path, int startFrom ) throws IOException {
    File f = new File( path );

    int len = (int)checkedFileLength( f, Integer.MAX_VALUE, startFrom ) - startFrom;
    byte[] data = new byte[len];
    int offset = 0;

    rater.start();
    InputStream ins = new FileInputStream( f );
    try {
      ins.skip( startFrom );
      while( offset < len ) {
        int got = ins.read( data, offset, len - offset );
        if( got < 0 ) {
          break;
        }
        offset += len;
        rater.increase( got );
      }
    } finally {
      IOUtils.closeQuietly( ins );
      rater.stop();
    }

    if( offset < len ) {
      String msg = "Failed to read file <" + path + ">: file size is " + len + " bytes, but only read " + offset
              + " bytes";
      throw new IOException( msg );
    }

    return data;
  }*/

}
